admin / Strike
publicWeb-Based UK Cyber Compliance Tool with Reporting
Strike / StrikeXi v3 / backend / app / itsm.py
2603 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | """ Future-proofing: ITSM integration layer. The roadmap items (RemediationAction rows) are deliberately modelled so they can be pushed to external systems. This module provides a pluggable adapter interface; the default is a no-op/log adapter. Swap in Jira/ServiceNow later without touching the assessment or scoring logic. To enable a real integration: 1. Implement an adapter (e.g. JiraAdapter.push(action) -> external_ref). 2. Register it in ADAPTERS. 3. Call push_actions(db, assessment_id, system="jira"). """ from abc import ABC, abstractmethod from sqlalchemy.orm import Session from . import models class ITSMAdapter(ABC): name = "base" @abstractmethod def push(self, action: models.RemediationAction, suggestion: models.RemediationSuggestion) -> str: """Create an external ticket and return its reference id.""" raise NotImplementedError class LogAdapter(ITSMAdapter): """Default safe adapter — records intent without external calls.""" name = "log" def push(self, action, suggestion) -> str: return f"LOG-{action.id.hex[:8]}" # Stubs showing the intended shape for future webhook/API integrations. class JiraAdapter(ITSMAdapter): name = "jira" def push(self, action, suggestion) -> str: # TODO: POST to {JIRA_URL}/rest/api/3/issue with auth + payload: # {"fields": {"project": {...}, "summary": suggestion.title, # "description": suggestion.detail, "issuetype": {"name": "Task"}}} return f"JIRA-STUB-{action.id.hex[:6]}" class ServiceNowAdapter(ITSMAdapter): name = "servicenow" def push(self, action, suggestion) -> str: # TODO: POST to {SN_URL}/api/now/table/incident with basic auth. return f"SN-STUB-{action.id.hex[:6]}" ADAPTERS = {a.name: a for a in [LogAdapter(), JiraAdapter(), ServiceNowAdapter()]} def push_actions(db: Session, assessment_id, system: str = "log") -> list[dict]: adapter = ADAPTERS.get(system, ADAPTERS["log"]) sugg = {s.id: s for s in db.query(models.RemediationSuggestion).all()} actions = ( db.query(models.RemediationAction) .filter(models.RemediationAction.assessment_id == assessment_id, models.RemediationAction.status == "queued").all() ) results = [] for a in actions: ref = adapter.push(a, sugg.get(a.remediation_id)) a.external_ref = ref a.external_system = adapter.name a.status = "exported" results.append({"action_id": str(a.id), "external_ref": ref, "system": adapter.name}) db.commit() return results |